X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fusb%2Fmusb-new%2Fmusb_uboot.c;h=9c8cc6e584439850310ee126c268346cadcbc613;hb=cf8dcc5d02c32173b74bf1b7600dd2b990a90b13;hp=e823ad1a747de6d5e62a34eb2b5857bb98a127c2;hpb=b918a0c6f694a58b54a7de949d0c720bc6671bd9;p=oweals%2Fu-boot.git diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index e823ad1a74..9c8cc6e584 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -1,6 +1,7 @@ #include +#include #include -#include +#include #include #include @@ -10,11 +11,17 @@ #include "musb_core.h" #include "musb_host.h" #include "musb_gadget.h" +#include "musb_uboot.h" -#ifdef CONFIG_MUSB_HOST -static struct musb *host; -static struct usb_hcd hcd; -static enum usb_device_speed host_speed; +#ifdef CONFIG_USB_MUSB_HOST +struct int_queue { + struct usb_host_endpoint hep; + struct urb urb; +}; + +#if !CONFIG_IS_ENABLED(DM_USB) +struct musb_host_data musb_host; +#endif static void musb_host_complete_urb(struct urb *urb) { @@ -22,39 +29,35 @@ static void musb_host_complete_urb(struct urb *urb) urb->dev->act_len = urb->actual_length; } -static struct usb_host_endpoint hep; -static struct urb urb; - -static struct urb *construct_urb(struct usb_device *dev, int endpoint_type, - unsigned long pipe, void *buffer, int len, - struct devrequest *setup, int interval) +static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep, + struct usb_device *dev, int endpoint_type, + unsigned long pipe, void *buffer, int len, + struct devrequest *setup, int interval) { int epnum = usb_pipeendpoint(pipe); int is_in = usb_pipein(pipe); - memset(&urb, 0, sizeof(struct urb)); - memset(&hep, 0, sizeof(struct usb_host_endpoint)); - INIT_LIST_HEAD(&hep.urb_list); - INIT_LIST_HEAD(&urb.urb_list); - urb.ep = &hep; - urb.complete = musb_host_complete_urb; - urb.status = -EINPROGRESS; - urb.dev = dev; - urb.pipe = pipe; - urb.transfer_buffer = buffer; - urb.transfer_dma = (unsigned long)buffer; - urb.transfer_buffer_length = len; - urb.setup_packet = (unsigned char *)setup; - - urb.ep->desc.wMaxPacketSize = + memset(urb, 0, sizeof(struct urb)); + memset(hep, 0, sizeof(struct usb_host_endpoint)); + INIT_LIST_HEAD(&hep->urb_list); + INIT_LIST_HEAD(&urb->urb_list); + urb->ep = hep; + urb->complete = musb_host_complete_urb; + urb->status = -EINPROGRESS; + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = buffer; + urb->transfer_dma = (unsigned long)buffer; + urb->transfer_buffer_length = len; + urb->setup_packet = (unsigned char *)setup; + + urb->ep->desc.wMaxPacketSize = __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] : dev->epmaxpacketout[epnum]); - urb.ep->desc.bmAttributes = endpoint_type; - urb.ep->desc.bEndpointAddress = + urb->ep->desc.bmAttributes = endpoint_type; + urb->ep->desc.bEndpointAddress = (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum; - urb.ep->desc.bInterval = interval; - - return &urb; + urb->ep->desc.bInterval = interval; } static int submit_urb(struct usb_hcd *hcd, struct urb *urb) @@ -83,98 +86,291 @@ static int submit_urb(struct usb_hcd *hcd, struct urb *urb) return urb->status; } -int submit_control_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len, struct devrequest *setup) +static int _musb_submit_control_msg(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, + void *buffer, int len, struct devrequest *setup) { - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe, - buffer, len, setup, 0); + construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_CONTROL, + pipe, buffer, len, setup, 0); /* Fix speed for non hub-attached devices */ - if (!dev->parent) - dev->speed = host_speed; + if (!usb_dev_get_parent(dev)) + dev->speed = host->host_speed; - return submit_urb(&hcd, urb); + return submit_urb(&host->hcd, &host->urb); } +static int _musb_submit_bulk_msg(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, void *buffer, int len) +{ + construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_BULK, + pipe, buffer, len, NULL, 0); + return submit_urb(&host->hcd, &host->urb); +} -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len) +static int _musb_submit_int_msg(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, + void *buffer, int len, int interval) { - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe, - buffer, len, NULL, 0); - return submit_urb(&hcd, urb); + construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe, + buffer, len, NULL, interval); + return submit_urb(&host->hcd, &host->urb); } -int submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len, int interval) +static struct int_queue *_musb_create_int_queue(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, int queuesize, + int elementsize, void *buffer, int interval) { - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe, - buffer, len, NULL, interval); - return submit_urb(&hcd, urb); + struct int_queue *queue; + int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe); + + if (queuesize != 1) { + printf("ERROR musb int-queues only support queuesize 1\n"); + return NULL; + } + + if (dev->int_pending & (1 << index)) { + printf("ERROR int-urb is already pending on pipe %lx\n", pipe); + return NULL; + } + + queue = malloc(sizeof(*queue)); + if (!queue) + return NULL; + + construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT, + pipe, buffer, elementsize, NULL, interval); + + ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0); + if (ret < 0) { + printf("Failed to enqueue URB to controller\n"); + free(queue); + return NULL; + } + + dev->int_pending |= 1 << index; + return queue; } -void usb_reset_root_port(void) +static int _musb_destroy_int_queue(struct musb_host_data *host, + struct usb_device *dev, struct int_queue *queue) { - void *mbase = host->mregs; + int index = usb_pipein(queue->urb.pipe) * 16 + + usb_pipeendpoint(queue->urb.pipe); + + if (queue->urb.status == -EINPROGRESS) + musb_urb_dequeue(&host->hcd, &queue->urb, -ETIME); + + dev->int_pending &= ~(1 << index); + free(queue); + return 0; +} + +static void *_musb_poll_int_queue(struct musb_host_data *host, + struct usb_device *dev, struct int_queue *queue) +{ + if (queue->urb.status != -EINPROGRESS) + return NULL; /* URB has already completed in a prev. poll */ + + host->host->isr(0, host->host); + + if (queue->urb.status != -EINPROGRESS) + return queue->urb.transfer_buffer; /* Done */ + + return NULL; /* URB still pending */ +} + +static int _musb_reset_root_port(struct musb_host_data *host, + struct usb_device *dev) +{ + void *mbase = host->host->mregs; u8 power; power = musb_readb(mbase, MUSB_POWER); power &= 0xf0; musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power); mdelay(50); + + if (host->host->ops->pre_root_reset_end) + host->host->ops->pre_root_reset_end(host->host); + power = musb_readb(mbase, MUSB_POWER); musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); - host->isr(0, host); - host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? + + if (host->host->ops->post_root_reset_end) + host->host->ops->post_root_reset_end(host->host); + + host->host->isr(0, host->host); + host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? USB_SPEED_HIGH : (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ? USB_SPEED_FULL : USB_SPEED_LOW; - mdelay((host_speed == USB_SPEED_LOW) ? 200 : 50); + mdelay((host->host_speed == USB_SPEED_LOW) ? 200 : 50); + + return 0; } -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) +int musb_lowlevel_init(struct musb_host_data *host) { void *mbase; /* USB spec says it may take up to 1 second for a device to connect */ unsigned long timeout = get_timer(0) + 1000; + int ret; - if (!host) { + if (!host->host) { printf("MUSB host is not registered\n"); return -ENODEV; } - musb_start(host); - mbase = host->mregs; + ret = musb_start(host->host); + if (ret) + return ret; + + mbase = host->host->mregs; do { if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM) break; } while (get_timer(0) < timeout); - if (get_timer(0) >= timeout) + if (get_timer(0) >= timeout) { + musb_stop(host->host); return -ENODEV; + } - usb_reset_root_port(); - host->is_active = 1; - hcd.hcd_priv = host; + _musb_reset_root_port(host, NULL); + host->host->is_active = 1; + host->hcd.hcd_priv = host->host; return 0; } +#if !CONFIG_IS_ENABLED(DM_USB) int usb_lowlevel_stop(int index) { - if (!host) { + if (!musb_host.host) { printf("MUSB host is not registered\n"); return -ENODEV; } - musb_stop(host); + musb_stop(musb_host.host); return 0; } -#endif /* CONFIG_MUSB_HOST */ -#ifdef CONFIG_MUSB_GADGET +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length) +{ + return _musb_submit_bulk_msg(&musb_host, dev, pipe, buffer, length); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length, struct devrequest *setup) +{ + return _musb_submit_control_msg(&musb_host, dev, pipe, buffer, length, setup); +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length, int interval) +{ + return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval); +} + +struct int_queue *create_int_queue(struct usb_device *dev, + unsigned long pipe, int queuesize, int elementsize, + void *buffer, int interval) +{ + return _musb_create_int_queue(&musb_host, dev, pipe, queuesize, elementsize, + buffer, interval); +} + +void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + return _musb_poll_int_queue(&musb_host, dev, queue); +} + +int destroy_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + return _musb_destroy_int_queue(&musb_host, dev, queue); +} + +int usb_reset_root_port(struct usb_device *dev) +{ + return _musb_reset_root_port(&musb_host, dev); +} + +int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) +{ + return musb_lowlevel_init(&musb_host); +} +#endif /* !CONFIG_IS_ENABLED(DM_USB) */ + +#if CONFIG_IS_ENABLED(DM_USB) +static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + struct devrequest *setup) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_submit_control_msg(host, udev, pipe, buffer, length, setup); +} + +static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_submit_bulk_msg(host, udev, pipe, buffer, length); +} + +static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + int interval) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval); +} + +static struct int_queue *musb_create_int_queue(struct udevice *dev, + struct usb_device *udev, unsigned long pipe, int queuesize, + int elementsize, void *buffer, int interval) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_create_int_queue(host, udev, pipe, queuesize, elementsize, + buffer, interval); +} + +static void *musb_poll_int_queue(struct udevice *dev, struct usb_device *udev, + struct int_queue *queue) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_poll_int_queue(host, udev, queue); +} + +static int musb_destroy_int_queue(struct udevice *dev, struct usb_device *udev, + struct int_queue *queue) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_destroy_int_queue(host, udev, queue); +} + +static int musb_reset_root_port(struct udevice *dev, struct usb_device *udev) +{ + struct musb_host_data *host = dev_get_priv(dev); + return _musb_reset_root_port(host, udev); +} + +struct dm_usb_ops musb_usb_ops = { + .control = musb_submit_control_msg, + .bulk = musb_submit_bulk_msg, + .interrupt = musb_submit_int_msg, + .create_int_queue = musb_create_int_queue, + .poll_int_queue = musb_poll_int_queue, + .destroy_int_queue = musb_destroy_int_queue, + .reset_root_port = musb_reset_root_port, +}; +#endif /* CONFIG_IS_ENABLED(DM_USB) */ +#endif /* CONFIG_USB_MUSB_HOST */ + +#if defined(CONFIG_USB_MUSB_GADGET) && !CONFIG_IS_ENABLED(DM_USB_GADGET) static struct musb *gadget; -int usb_gadget_handle_interrupts(void) +int usb_gadget_handle_interrupts(int index) { WATCHDOG_RESET(); if (!gadget || !gadget->isr) @@ -221,33 +417,33 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) driver->unbind(&gadget->g); return 0; } -#endif /* CONFIG_MUSB_GADGET */ +#endif /* CONFIG_USB_MUSB_GADGET */ -int musb_register(struct musb_hdrc_platform_data *plat, void *bdata, - void *ctl_regs) +struct musb *musb_register(struct musb_hdrc_platform_data *plat, void *bdata, + void *ctl_regs) { struct musb **musbp; switch (plat->mode) { -#ifdef CONFIG_MUSB_HOST +#if defined(CONFIG_USB_MUSB_HOST) && !CONFIG_IS_ENABLED(DM_USB) case MUSB_HOST: - musbp = &host; + musbp = &musb_host.host; break; #endif -#ifdef CONFIG_MUSB_GADGET +#if defined(CONFIG_USB_MUSB_GADGET) && !CONFIG_IS_ENABLED(DM_USB_GADGET) case MUSB_PERIPHERAL: musbp = &gadget; break; #endif default: - return -EINVAL; + return ERR_PTR(-EINVAL); } *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs); - if (!musbp) { + if (IS_ERR(*musbp)) { printf("Failed to init the controller\n"); - return -EIO; + return ERR_CAST(*musbp); } - return 0; + return *musbp; }