X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fusb%2Fmusb-new%2Fmusb_uboot.c;h=233a0e4a5e297363532c6c2bc338fe2598094581;hb=d83c25c318564080ce647795e5ee49133b97e87d;hp=6e58ddf02cc34b67b4550b9f752d5a00c2d0615c;hpb=768f6096f9c389b5ed36bee2957bee16b085fc4a;p=u-boot diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 6e58ddf02c..233a0e4a5e 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -1,5 +1,9 @@ #include +#include #include +#ifdef CONFIG_ARCH_SUNXI +#include +#endif #include #include #include @@ -10,16 +14,17 @@ #include "musb_core.h" #include "musb_host.h" #include "musb_gadget.h" +#include "musb_uboot.h" -#ifdef CONFIG_MUSB_HOST +#ifdef CONFIG_USB_MUSB_HOST struct int_queue { struct usb_host_endpoint hep; struct urb urb; }; -static struct musb *host; -static struct usb_hcd hcd; -static enum usb_device_speed host_speed; +#ifndef CONFIG_DM_USB +struct musb_host_data musb_host; +#endif static void musb_host_complete_urb(struct urb *urb) { @@ -27,9 +32,6 @@ 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 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, @@ -87,38 +89,40 @@ 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) { - construct_urb(&urb, &hep, 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); } - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len) +static int _musb_submit_bulk_msg(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, void *buffer, int len) { - construct_urb(&urb, &hep, 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_BULK, + pipe, buffer, len, NULL, 0); + 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 int _musb_submit_int_msg(struct musb_host_data *host, + struct usb_device *dev, unsigned long pipe, + void *buffer, int len, int interval) { - construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_INT, pipe, + construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, len, NULL, interval); - return submit_urb(&hcd, &urb); + return submit_urb(&host->hcd, &host->urb); } -struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe, - int queuesize, int elementsize, void *buffer, 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 int_queue *queue; int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe); @@ -140,7 +144,7 @@ struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe, construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, elementsize, NULL, interval); - ret = musb_urb_enqueue(&hcd, &queue->urb, 0); + ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0); if (ret < 0) { printf("Failed to enqueue URB to controller\n"); free(queue); @@ -151,25 +155,27 @@ struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe, return queue; } -int destroy_int_queue(struct usb_device *dev, struct int_queue *queue) +static int _musb_destroy_int_queue(struct musb_host_data *host, + struct usb_device *dev, struct int_queue *queue) { int index = usb_pipein(queue->urb.pipe) * 16 + usb_pipeendpoint(queue->urb.pipe); if (queue->urb.status == -EINPROGRESS) - musb_urb_dequeue(&hcd, &queue->urb, -ETIME); + musb_urb_dequeue(&host->hcd, &queue->urb, -ETIME); dev->int_pending &= ~(1 << index); free(queue); return 0; } -void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) +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->isr(0, host); + host->host->isr(0, host->host); if (queue->urb.status != -EINPROGRESS) return queue->urb.transfer_buffer; /* Done */ @@ -177,38 +183,56 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) return NULL; /* URB still pending */ } -void usb_reset_root_port(void) +static int _musb_reset_root_port(struct musb_host_data *host, + struct usb_device *dev) { - void *mbase = host->mregs; + 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); +#ifdef CONFIG_ARCH_SUNXI + /* + * sunxi phy has a bug and it will wrongly detect high speed squelch + * when clearing reset on low-speed devices, temporary disable + * squelch detection to work around this. + */ + sunxi_usb_phy_enable_squelch_detect(0, 0); +#endif 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) ? +#ifdef CONFIG_ARCH_SUNXI + sunxi_usb_phy_enable_squelch_detect(0, 1); +#endif + 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; @@ -216,29 +240,141 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) if (get_timer(0) >= timeout) 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; } +#ifndef CONFIG_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_DM_USB */ + +#ifdef CONFIG_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_DM_USB */ +#endif /* CONFIG_USB_MUSB_HOST */ + +#ifdef CONFIG_USB_MUSB_GADGET static struct musb *gadget; -int usb_gadget_handle_interrupts(void) +int usb_gadget_handle_interrupts(int index) { WATCHDOG_RESET(); if (!gadget || !gadget->isr) @@ -285,7 +421,7 @@ 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) @@ -293,12 +429,12 @@ int musb_register(struct musb_hdrc_platform_data *plat, void *bdata, struct musb **musbp; switch (plat->mode) { -#ifdef CONFIG_MUSB_HOST +#if defined(CONFIG_USB_MUSB_HOST) && !defined(CONFIG_DM_USB) case MUSB_HOST: - musbp = &host; + musbp = &musb_host.host; break; #endif -#ifdef CONFIG_MUSB_GADGET +#ifdef CONFIG_USB_MUSB_GADGET case MUSB_PERIPHERAL: musbp = &gadget; break;