1eb81955bSIlya Yanok #include <common.h> 224b852a7SSimon Glass #include <console.h> 37a342785SHeiko Schocher #include <watchdog.h> 41221ce45SMasahiro Yamada #include <linux/errno.h> 5eb81955bSIlya Yanok #include <linux/usb/ch9.h> 6eb81955bSIlya Yanok #include <linux/usb/gadget.h> 7eb81955bSIlya Yanok 8eb81955bSIlya Yanok #include <usb.h> 9eb81955bSIlya Yanok #include "linux-compat.h" 10eb81955bSIlya Yanok #include "usb-compat.h" 11eb81955bSIlya Yanok #include "musb_core.h" 12eb81955bSIlya Yanok #include "musb_host.h" 13eb81955bSIlya Yanok #include "musb_gadget.h" 14fc85d39eSHans de Goede #include "musb_uboot.h" 15eb81955bSIlya Yanok 1695de1e2fSPaul Kocialkowski #ifdef CONFIG_USB_MUSB_HOST 17904f2a83SHans de Goede struct int_queue { 18904f2a83SHans de Goede struct usb_host_endpoint hep; 19904f2a83SHans de Goede struct urb urb; 20904f2a83SHans de Goede }; 21904f2a83SHans de Goede 22*fd09c205SSven Schwermer #if !CONFIG_IS_ENABLED(DM_USB) 23fc85d39eSHans de Goede struct musb_host_data musb_host; 2409e7ea47SHans de Goede #endif 25eb81955bSIlya Yanok 26eb81955bSIlya Yanok static void musb_host_complete_urb(struct urb *urb) 27eb81955bSIlya Yanok { 28eb81955bSIlya Yanok urb->dev->status &= ~USB_ST_NOT_PROC; 29eb81955bSIlya Yanok urb->dev->act_len = urb->actual_length; 30eb81955bSIlya Yanok } 31eb81955bSIlya Yanok 32accf04c2SHans de Goede static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep, 33accf04c2SHans de Goede struct usb_device *dev, int endpoint_type, 34eb81955bSIlya Yanok unsigned long pipe, void *buffer, int len, 35eb81955bSIlya Yanok struct devrequest *setup, int interval) 36eb81955bSIlya Yanok { 37eb81955bSIlya Yanok int epnum = usb_pipeendpoint(pipe); 38eb81955bSIlya Yanok int is_in = usb_pipein(pipe); 39eb81955bSIlya Yanok 40accf04c2SHans de Goede memset(urb, 0, sizeof(struct urb)); 41accf04c2SHans de Goede memset(hep, 0, sizeof(struct usb_host_endpoint)); 42accf04c2SHans de Goede INIT_LIST_HEAD(&hep->urb_list); 43accf04c2SHans de Goede INIT_LIST_HEAD(&urb->urb_list); 44accf04c2SHans de Goede urb->ep = hep; 45accf04c2SHans de Goede urb->complete = musb_host_complete_urb; 46accf04c2SHans de Goede urb->status = -EINPROGRESS; 47accf04c2SHans de Goede urb->dev = dev; 48accf04c2SHans de Goede urb->pipe = pipe; 49accf04c2SHans de Goede urb->transfer_buffer = buffer; 50accf04c2SHans de Goede urb->transfer_dma = (unsigned long)buffer; 51accf04c2SHans de Goede urb->transfer_buffer_length = len; 52accf04c2SHans de Goede urb->setup_packet = (unsigned char *)setup; 53eb81955bSIlya Yanok 54accf04c2SHans de Goede urb->ep->desc.wMaxPacketSize = 55eb81955bSIlya Yanok __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] : 56eb81955bSIlya Yanok dev->epmaxpacketout[epnum]); 57accf04c2SHans de Goede urb->ep->desc.bmAttributes = endpoint_type; 58accf04c2SHans de Goede urb->ep->desc.bEndpointAddress = 59eb81955bSIlya Yanok (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum; 60accf04c2SHans de Goede urb->ep->desc.bInterval = interval; 61eb81955bSIlya Yanok } 62eb81955bSIlya Yanok 63eb81955bSIlya Yanok static int submit_urb(struct usb_hcd *hcd, struct urb *urb) 64eb81955bSIlya Yanok { 65eb81955bSIlya Yanok struct musb *host = hcd->hcd_priv; 66eb81955bSIlya Yanok int ret; 67dc9a3912SHans de Goede unsigned long timeout; 68eb81955bSIlya Yanok 69eb81955bSIlya Yanok ret = musb_urb_enqueue(hcd, urb, 0); 70eb81955bSIlya Yanok if (ret < 0) { 71eb81955bSIlya Yanok printf("Failed to enqueue URB to controller\n"); 72eb81955bSIlya Yanok return ret; 73eb81955bSIlya Yanok } 74eb81955bSIlya Yanok 75dc9a3912SHans de Goede timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe); 76eb81955bSIlya Yanok do { 77eb81955bSIlya Yanok if (ctrlc()) 78eb81955bSIlya Yanok return -EIO; 79eb81955bSIlya Yanok host->isr(0, host); 80e8672e3fSHans de Goede } while (urb->status == -EINPROGRESS && 81dc9a3912SHans de Goede get_timer(0) < timeout); 82eb81955bSIlya Yanok 83b918a0c6SHans de Goede if (urb->status == -EINPROGRESS) 84b918a0c6SHans de Goede musb_urb_dequeue(hcd, urb, -ETIME); 85b918a0c6SHans de Goede 86eb81955bSIlya Yanok return urb->status; 87eb81955bSIlya Yanok } 88eb81955bSIlya Yanok 89fc85d39eSHans de Goede static int _musb_submit_control_msg(struct musb_host_data *host, 90fc85d39eSHans de Goede struct usb_device *dev, unsigned long pipe, 91eb81955bSIlya Yanok void *buffer, int len, struct devrequest *setup) 92eb81955bSIlya Yanok { 93fc85d39eSHans de Goede construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_CONTROL, 94fc85d39eSHans de Goede pipe, buffer, len, setup, 0); 95eb81955bSIlya Yanok 96eb81955bSIlya Yanok /* Fix speed for non hub-attached devices */ 97e740ca3cSHans de Goede if (!usb_dev_get_parent(dev)) 98fc85d39eSHans de Goede dev->speed = host->host_speed; 99eb81955bSIlya Yanok 100fc85d39eSHans de Goede return submit_urb(&host->hcd, &host->urb); 101eb81955bSIlya Yanok } 102eb81955bSIlya Yanok 103fc85d39eSHans de Goede static int _musb_submit_bulk_msg(struct musb_host_data *host, 104fc85d39eSHans de Goede struct usb_device *dev, unsigned long pipe, void *buffer, int len) 105eb81955bSIlya Yanok { 106fc85d39eSHans de Goede construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_BULK, 107fc85d39eSHans de Goede pipe, buffer, len, NULL, 0); 108fc85d39eSHans de Goede return submit_urb(&host->hcd, &host->urb); 109eb81955bSIlya Yanok } 110eb81955bSIlya Yanok 111fc85d39eSHans de Goede static int _musb_submit_int_msg(struct musb_host_data *host, 112fc85d39eSHans de Goede struct usb_device *dev, unsigned long pipe, 113eb81955bSIlya Yanok void *buffer, int len, int interval) 114eb81955bSIlya Yanok { 115fc85d39eSHans de Goede construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe, 116eb81955bSIlya Yanok buffer, len, NULL, interval); 117fc85d39eSHans de Goede return submit_urb(&host->hcd, &host->urb); 118eb81955bSIlya Yanok } 119eb81955bSIlya Yanok 120fc85d39eSHans de Goede static struct int_queue *_musb_create_int_queue(struct musb_host_data *host, 121fc85d39eSHans de Goede struct usb_device *dev, unsigned long pipe, int queuesize, 122fc85d39eSHans de Goede int elementsize, void *buffer, int interval) 123904f2a83SHans de Goede { 124904f2a83SHans de Goede struct int_queue *queue; 125904f2a83SHans de Goede int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe); 126904f2a83SHans de Goede 127904f2a83SHans de Goede if (queuesize != 1) { 128904f2a83SHans de Goede printf("ERROR musb int-queues only support queuesize 1\n"); 129904f2a83SHans de Goede return NULL; 130904f2a83SHans de Goede } 131904f2a83SHans de Goede 132904f2a83SHans de Goede if (dev->int_pending & (1 << index)) { 133904f2a83SHans de Goede printf("ERROR int-urb is already pending on pipe %lx\n", pipe); 134904f2a83SHans de Goede return NULL; 135904f2a83SHans de Goede } 136904f2a83SHans de Goede 137904f2a83SHans de Goede queue = malloc(sizeof(*queue)); 138904f2a83SHans de Goede if (!queue) 139904f2a83SHans de Goede return NULL; 140904f2a83SHans de Goede 141904f2a83SHans de Goede construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT, 142904f2a83SHans de Goede pipe, buffer, elementsize, NULL, interval); 143904f2a83SHans de Goede 144fc85d39eSHans de Goede ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0); 145904f2a83SHans de Goede if (ret < 0) { 146904f2a83SHans de Goede printf("Failed to enqueue URB to controller\n"); 147904f2a83SHans de Goede free(queue); 148904f2a83SHans de Goede return NULL; 149904f2a83SHans de Goede } 150904f2a83SHans de Goede 151904f2a83SHans de Goede dev->int_pending |= 1 << index; 152904f2a83SHans de Goede return queue; 153904f2a83SHans de Goede } 154904f2a83SHans de Goede 155fc85d39eSHans de Goede static int _musb_destroy_int_queue(struct musb_host_data *host, 156fc85d39eSHans de Goede struct usb_device *dev, struct int_queue *queue) 157904f2a83SHans de Goede { 158904f2a83SHans de Goede int index = usb_pipein(queue->urb.pipe) * 16 + 159904f2a83SHans de Goede usb_pipeendpoint(queue->urb.pipe); 160904f2a83SHans de Goede 161904f2a83SHans de Goede if (queue->urb.status == -EINPROGRESS) 162fc85d39eSHans de Goede musb_urb_dequeue(&host->hcd, &queue->urb, -ETIME); 163904f2a83SHans de Goede 164904f2a83SHans de Goede dev->int_pending &= ~(1 << index); 165904f2a83SHans de Goede free(queue); 166904f2a83SHans de Goede return 0; 167904f2a83SHans de Goede } 168904f2a83SHans de Goede 169fc85d39eSHans de Goede static void *_musb_poll_int_queue(struct musb_host_data *host, 170fc85d39eSHans de Goede struct usb_device *dev, struct int_queue *queue) 171904f2a83SHans de Goede { 172904f2a83SHans de Goede if (queue->urb.status != -EINPROGRESS) 173904f2a83SHans de Goede return NULL; /* URB has already completed in a prev. poll */ 174904f2a83SHans de Goede 175fc85d39eSHans de Goede host->host->isr(0, host->host); 176904f2a83SHans de Goede 177904f2a83SHans de Goede if (queue->urb.status != -EINPROGRESS) 178904f2a83SHans de Goede return queue->urb.transfer_buffer; /* Done */ 179904f2a83SHans de Goede 180904f2a83SHans de Goede return NULL; /* URB still pending */ 181904f2a83SHans de Goede } 182904f2a83SHans de Goede 183fc85d39eSHans de Goede static int _musb_reset_root_port(struct musb_host_data *host, 184fc85d39eSHans de Goede struct usb_device *dev) 18590cdc103SHans de Goede { 186fc85d39eSHans de Goede void *mbase = host->host->mregs; 18790cdc103SHans de Goede u8 power; 18890cdc103SHans de Goede 18990cdc103SHans de Goede power = musb_readb(mbase, MUSB_POWER); 19090cdc103SHans de Goede power &= 0xf0; 19190cdc103SHans de Goede musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power); 19290cdc103SHans de Goede mdelay(50); 193aa29b11bSJagan Teki 194aa29b11bSJagan Teki if (host->host->ops->pre_root_reset_end) 195aa29b11bSJagan Teki host->host->ops->pre_root_reset_end(host->host); 196aa29b11bSJagan Teki 19790cdc103SHans de Goede power = musb_readb(mbase, MUSB_POWER); 19890cdc103SHans de Goede musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); 199aa29b11bSJagan Teki 200aa29b11bSJagan Teki if (host->host->ops->post_root_reset_end) 201aa29b11bSJagan Teki host->host->ops->post_root_reset_end(host->host); 202aa29b11bSJagan Teki 203fc85d39eSHans de Goede host->host->isr(0, host->host); 204fc85d39eSHans de Goede host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? 20590cdc103SHans de Goede USB_SPEED_HIGH : 20690cdc103SHans de Goede (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ? 20790cdc103SHans de Goede USB_SPEED_FULL : USB_SPEED_LOW; 208fc85d39eSHans de Goede mdelay((host->host_speed == USB_SPEED_LOW) ? 200 : 50); 209de31213fSSimon Glass 210de31213fSSimon Glass return 0; 21190cdc103SHans de Goede } 21290cdc103SHans de Goede 213fc85d39eSHans de Goede int musb_lowlevel_init(struct musb_host_data *host) 214eb81955bSIlya Yanok { 215eb81955bSIlya Yanok void *mbase; 216dc9a3912SHans de Goede /* USB spec says it may take up to 1 second for a device to connect */ 217dc9a3912SHans de Goede unsigned long timeout = get_timer(0) + 1000; 21815837236SHans de Goede int ret; 219eb81955bSIlya Yanok 220fc85d39eSHans de Goede if (!host->host) { 221eb81955bSIlya Yanok printf("MUSB host is not registered\n"); 222eb81955bSIlya Yanok return -ENODEV; 223eb81955bSIlya Yanok } 224eb81955bSIlya Yanok 225fc85d39eSHans de Goede ret = musb_start(host->host); 22615837236SHans de Goede if (ret) 22715837236SHans de Goede return ret; 22815837236SHans de Goede 229fc85d39eSHans de Goede mbase = host->host->mregs; 230eb81955bSIlya Yanok do { 231eb81955bSIlya Yanok if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM) 232eb81955bSIlya Yanok break; 233dc9a3912SHans de Goede } while (get_timer(0) < timeout); 234bf313230SHans de Goede if (get_timer(0) >= timeout) { 235bf313230SHans de Goede musb_stop(host->host); 236eb81955bSIlya Yanok return -ENODEV; 237bf313230SHans de Goede } 238eb81955bSIlya Yanok 239fc85d39eSHans de Goede _musb_reset_root_port(host, NULL); 240fc85d39eSHans de Goede host->host->is_active = 1; 241fc85d39eSHans de Goede host->hcd.hcd_priv = host->host; 242eb81955bSIlya Yanok 243eb81955bSIlya Yanok return 0; 244eb81955bSIlya Yanok } 245eb81955bSIlya Yanok 246*fd09c205SSven Schwermer #if !CONFIG_IS_ENABLED(DM_USB) 247eb81955bSIlya Yanok int usb_lowlevel_stop(int index) 248eb81955bSIlya Yanok { 249fc85d39eSHans de Goede if (!musb_host.host) { 250eb81955bSIlya Yanok printf("MUSB host is not registered\n"); 251eb81955bSIlya Yanok return -ENODEV; 252eb81955bSIlya Yanok } 253eb81955bSIlya Yanok 254fc85d39eSHans de Goede musb_stop(musb_host.host); 255eb81955bSIlya Yanok return 0; 256eb81955bSIlya Yanok } 2571398252aSHans de Goede 2581398252aSHans de Goede int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, 2591398252aSHans de Goede void *buffer, int length) 2601398252aSHans de Goede { 261fc85d39eSHans de Goede return _musb_submit_bulk_msg(&musb_host, dev, pipe, buffer, length); 2621398252aSHans de Goede } 2631398252aSHans de Goede 2641398252aSHans de Goede int submit_control_msg(struct usb_device *dev, unsigned long pipe, 2651398252aSHans de Goede void *buffer, int length, struct devrequest *setup) 2661398252aSHans de Goede { 267fc85d39eSHans de Goede return _musb_submit_control_msg(&musb_host, dev, pipe, buffer, length, setup); 2681398252aSHans de Goede } 2691398252aSHans de Goede 2701398252aSHans de Goede int submit_int_msg(struct usb_device *dev, unsigned long pipe, 2711398252aSHans de Goede void *buffer, int length, int interval) 2721398252aSHans de Goede { 273fc85d39eSHans de Goede return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval); 2741398252aSHans de Goede } 2751398252aSHans de Goede 2761398252aSHans de Goede struct int_queue *create_int_queue(struct usb_device *dev, 2771398252aSHans de Goede unsigned long pipe, int queuesize, int elementsize, 2781398252aSHans de Goede void *buffer, int interval) 2791398252aSHans de Goede { 280fc85d39eSHans de Goede return _musb_create_int_queue(&musb_host, dev, pipe, queuesize, elementsize, 2811398252aSHans de Goede buffer, interval); 2821398252aSHans de Goede } 2831398252aSHans de Goede 2841398252aSHans de Goede void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) 2851398252aSHans de Goede { 286fc85d39eSHans de Goede return _musb_poll_int_queue(&musb_host, dev, queue); 2871398252aSHans de Goede } 2881398252aSHans de Goede 2891398252aSHans de Goede int destroy_int_queue(struct usb_device *dev, struct int_queue *queue) 2901398252aSHans de Goede { 291fc85d39eSHans de Goede return _musb_destroy_int_queue(&musb_host, dev, queue); 2921398252aSHans de Goede } 2931398252aSHans de Goede 2941398252aSHans de Goede int usb_reset_root_port(struct usb_device *dev) 2951398252aSHans de Goede { 296fc85d39eSHans de Goede return _musb_reset_root_port(&musb_host, dev); 2971398252aSHans de Goede } 2981398252aSHans de Goede 2991398252aSHans de Goede int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) 3001398252aSHans de Goede { 301fc85d39eSHans de Goede return musb_lowlevel_init(&musb_host); 3021398252aSHans de Goede } 303*fd09c205SSven Schwermer #endif /* !CONFIG_IS_ENABLED(DM_USB) */ 30409e7ea47SHans de Goede 305*fd09c205SSven Schwermer #if CONFIG_IS_ENABLED(DM_USB) 30609e7ea47SHans de Goede static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev, 30709e7ea47SHans de Goede unsigned long pipe, void *buffer, int length, 30809e7ea47SHans de Goede struct devrequest *setup) 30909e7ea47SHans de Goede { 31009e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 31109e7ea47SHans de Goede return _musb_submit_control_msg(host, udev, pipe, buffer, length, setup); 31209e7ea47SHans de Goede } 31309e7ea47SHans de Goede 31409e7ea47SHans de Goede static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, 31509e7ea47SHans de Goede unsigned long pipe, void *buffer, int length) 31609e7ea47SHans de Goede { 31709e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 31809e7ea47SHans de Goede return _musb_submit_bulk_msg(host, udev, pipe, buffer, length); 31909e7ea47SHans de Goede } 32009e7ea47SHans de Goede 32109e7ea47SHans de Goede static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev, 32209e7ea47SHans de Goede unsigned long pipe, void *buffer, int length, 32309e7ea47SHans de Goede int interval) 32409e7ea47SHans de Goede { 32509e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 32609e7ea47SHans de Goede return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval); 32709e7ea47SHans de Goede } 32809e7ea47SHans de Goede 32909e7ea47SHans de Goede static struct int_queue *musb_create_int_queue(struct udevice *dev, 33009e7ea47SHans de Goede struct usb_device *udev, unsigned long pipe, int queuesize, 33109e7ea47SHans de Goede int elementsize, void *buffer, int interval) 33209e7ea47SHans de Goede { 33309e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 33409e7ea47SHans de Goede return _musb_create_int_queue(host, udev, pipe, queuesize, elementsize, 33509e7ea47SHans de Goede buffer, interval); 33609e7ea47SHans de Goede } 33709e7ea47SHans de Goede 33809e7ea47SHans de Goede static void *musb_poll_int_queue(struct udevice *dev, struct usb_device *udev, 33909e7ea47SHans de Goede struct int_queue *queue) 34009e7ea47SHans de Goede { 34109e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 34209e7ea47SHans de Goede return _musb_poll_int_queue(host, udev, queue); 34309e7ea47SHans de Goede } 34409e7ea47SHans de Goede 34509e7ea47SHans de Goede static int musb_destroy_int_queue(struct udevice *dev, struct usb_device *udev, 34609e7ea47SHans de Goede struct int_queue *queue) 34709e7ea47SHans de Goede { 34809e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 34909e7ea47SHans de Goede return _musb_destroy_int_queue(host, udev, queue); 35009e7ea47SHans de Goede } 35109e7ea47SHans de Goede 35209e7ea47SHans de Goede static int musb_reset_root_port(struct udevice *dev, struct usb_device *udev) 35309e7ea47SHans de Goede { 35409e7ea47SHans de Goede struct musb_host_data *host = dev_get_priv(dev); 35509e7ea47SHans de Goede return _musb_reset_root_port(host, udev); 35609e7ea47SHans de Goede } 35709e7ea47SHans de Goede 35809e7ea47SHans de Goede struct dm_usb_ops musb_usb_ops = { 35909e7ea47SHans de Goede .control = musb_submit_control_msg, 36009e7ea47SHans de Goede .bulk = musb_submit_bulk_msg, 36109e7ea47SHans de Goede .interrupt = musb_submit_int_msg, 36209e7ea47SHans de Goede .create_int_queue = musb_create_int_queue, 36309e7ea47SHans de Goede .poll_int_queue = musb_poll_int_queue, 36409e7ea47SHans de Goede .destroy_int_queue = musb_destroy_int_queue, 36509e7ea47SHans de Goede .reset_root_port = musb_reset_root_port, 36609e7ea47SHans de Goede }; 367*fd09c205SSven Schwermer #endif /* CONFIG_IS_ENABLED(DM_USB) */ 36895de1e2fSPaul Kocialkowski #endif /* CONFIG_USB_MUSB_HOST */ 369eb81955bSIlya Yanok 37095de1e2fSPaul Kocialkowski #ifdef CONFIG_USB_MUSB_GADGET 371eb81955bSIlya Yanok static struct musb *gadget; 372eb81955bSIlya Yanok 3732d48aa69SKishon Vijay Abraham I int usb_gadget_handle_interrupts(int index) 374eb81955bSIlya Yanok { 3757a342785SHeiko Schocher WATCHDOG_RESET(); 376eb81955bSIlya Yanok if (!gadget || !gadget->isr) 377eb81955bSIlya Yanok return -EINVAL; 378eb81955bSIlya Yanok 379eb81955bSIlya Yanok return gadget->isr(0, gadget); 380eb81955bSIlya Yanok } 381eb81955bSIlya Yanok 382eb81955bSIlya Yanok int usb_gadget_register_driver(struct usb_gadget_driver *driver) 383eb81955bSIlya Yanok { 384eb81955bSIlya Yanok int ret; 385eb81955bSIlya Yanok 38676b09b85SBin Liu if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || 387eb81955bSIlya Yanok !driver->setup) { 388eb81955bSIlya Yanok printf("bad parameter.\n"); 389eb81955bSIlya Yanok return -EINVAL; 390eb81955bSIlya Yanok } 391eb81955bSIlya Yanok 392eb81955bSIlya Yanok if (!gadget) { 393eb81955bSIlya Yanok printf("Controller uninitialized\n"); 394eb81955bSIlya Yanok return -ENXIO; 395eb81955bSIlya Yanok } 396eb81955bSIlya Yanok 397eb81955bSIlya Yanok ret = musb_gadget_start(&gadget->g, driver); 398eb81955bSIlya Yanok if (ret < 0) { 399eb81955bSIlya Yanok printf("gadget_start failed with %d\n", ret); 400eb81955bSIlya Yanok return ret; 401eb81955bSIlya Yanok } 402eb81955bSIlya Yanok 403eb81955bSIlya Yanok ret = driver->bind(&gadget->g); 404eb81955bSIlya Yanok if (ret < 0) { 405eb81955bSIlya Yanok printf("bind failed with %d\n", ret); 406eb81955bSIlya Yanok return ret; 407eb81955bSIlya Yanok } 408eb81955bSIlya Yanok 409eb81955bSIlya Yanok return 0; 410eb81955bSIlya Yanok } 411eb81955bSIlya Yanok 412eb81955bSIlya Yanok int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) 413eb81955bSIlya Yanok { 414078d7302SRob Herring if (driver->disconnect) 415078d7302SRob Herring driver->disconnect(&gadget->g); 416078d7302SRob Herring if (driver->unbind) 417078d7302SRob Herring driver->unbind(&gadget->g); 418eb81955bSIlya Yanok return 0; 419eb81955bSIlya Yanok } 42095de1e2fSPaul Kocialkowski #endif /* CONFIG_USB_MUSB_GADGET */ 421eb81955bSIlya Yanok 4228b8d59f3SJagan Teki struct musb *musb_register(struct musb_hdrc_platform_data *plat, void *bdata, 423eb81955bSIlya Yanok void *ctl_regs) 424eb81955bSIlya Yanok { 425eb81955bSIlya Yanok struct musb **musbp; 426eb81955bSIlya Yanok 427eb81955bSIlya Yanok switch (plat->mode) { 428*fd09c205SSven Schwermer #if defined(CONFIG_USB_MUSB_HOST) && !CONFIG_IS_ENABLED(DM_USB) 429eb81955bSIlya Yanok case MUSB_HOST: 430fc85d39eSHans de Goede musbp = &musb_host.host; 431eb81955bSIlya Yanok break; 432eb81955bSIlya Yanok #endif 43395de1e2fSPaul Kocialkowski #ifdef CONFIG_USB_MUSB_GADGET 434eb81955bSIlya Yanok case MUSB_PERIPHERAL: 435eb81955bSIlya Yanok musbp = &gadget; 436eb81955bSIlya Yanok break; 437eb81955bSIlya Yanok #endif 438eb81955bSIlya Yanok default: 4398b8d59f3SJagan Teki return ERR_PTR(-EINVAL); 440eb81955bSIlya Yanok } 441eb81955bSIlya Yanok 442eb81955bSIlya Yanok *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs); 4438b8d59f3SJagan Teki if (IS_ERR(*musbp)) { 444eb81955bSIlya Yanok printf("Failed to init the controller\n"); 4458b8d59f3SJagan Teki return ERR_CAST(*musbp); 446eb81955bSIlya Yanok } 447eb81955bSIlya Yanok 4488b8d59f3SJagan Teki return *musbp; 449eb81955bSIlya Yanok } 450